﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FySystem.Job.JobTask
{
    /// <summary>
    /// 每天指定时间点执行的定时任务，每月和每年的定时任务不再单独写类，可以用该类变相实现，
    /// 比如需要每月1号的00:00:00分执行任务，则创建一个每天00:00:00执行的定时任务，然后在
    /// 每天00:00:00执行的时候判断是否为1号，如果是则执行后续逻辑，如果不是则return。
    /// </summary>
    public class DailyJob : JobBase
    {
        /// <summary>
        /// 每天执行小时时间点
        /// </summary>
        public int Hour { get; private set; } = 0;
        /// <summary>
        /// 每天执行的分钟时间点
        /// </summary>
        public int Minute { get; private set; } = 0;
        /// <summary>
        /// 每天执行的秒时间点
        /// </summary>
        public int Second { get; private set; } = 0;

        public DailyJob(string jobName, FyJobContext.FyJobAction jobExecuter, int hour, int min, int second) : base(jobName, jobExecuter)
        {
            try
            {
                Hour = hour;
                Minute = min;
                Second = second;

                //初始化定时任务
                InitializeJob();
            }
            catch (Exception)
            {
                throw;
            }
        }

        private void InitializeJob()
        {
            try
            {
                //是否执行
                ExecuteTrigger = job =>
                {
                    bool res = false;
                    try
                    {
                        if (DateTime.Now >= NextExecuteTime)
                            res = true;
                    }
                    catch { }
                    return res;
                };

                //下次执行时间
                NextExecuteTimeGenerator = job =>
                {
                    DateTime res = DateTime.MaxValue;
                    try
                    {
                        DateTime startTime = DateTime.Now;

                        //如果当前时间已经超过了今天的执行时间，则从明天开始计算
                        if (startTime.Hour >= Hour && startTime.Minute >= Minute && startTime.Second >= Second)
                        {
                            DateTime nextDay = DateTime.Now.AddDays(1);
                            startTime = new DateTime(nextDay.Year, nextDay.Month, nextDay.Day);
                        }

                        DateTime endTime = DateTime.Now.AddDays(2);

                        while (startTime <= endTime)
                        {
                            if (startTime.Hour == Hour && startTime.Minute == Minute && startTime.Second == Second)
                            {
                                res = startTime;
                                break;
                            }

                            startTime = startTime.AddSeconds(1);
                        }
                    }
                    catch { }
                    return res;
                };
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
}
